package com.sunxd.zstudy.juc.T20_ThreadPool.threadPool;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.SneakyThrows;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 工作窃取是指当某个线程的任务队列中没有可执行任务的时候，从其他线程的任务队列中窃取任务来执行，以充分利用工作线程的计算能力，减少线程由于获取不到任务而造成的空闲浪费。在ForkJoinpool中，工作任务的队列都采用双端队列Deque容器
 * 带返回值的RecursiveTask和不带返回值的RecursiveAction类
 *
 * @author: 作者名称
 * @date: 2021-09-14 16:29
 **/
public class T2_2_ForkJoinPool {

    static int[] numbers = new int[10000000];
    static Random r = new Random();

    static {
        for (int i = 0; i < numbers.length; i++) {
            numbers[i] = r.nextInt(10);
        }

        System.out.println("---" + Arrays.stream(numbers).sum()); //stream api
    }


    public static void main(String[] args) throws IOException {

        ForkJoinPool fjp = new ForkJoinPool();
        SumTask task = new SumTask(0, numbers.length);
        fjp.execute(task);
        long result = task.join();
        System.out.println("result: "+ result);
//        System.in.read();

    }

    @EqualsAndHashCode(callSuper = true)
    @Data
    static class SumTask extends RecursiveTask<Long> {

        private int start;
        private int end;

        public SumTask(int start, int end) {
            this.start = start;
            this.end = end;
        }

        @Override
        protected Long compute() {
            if (end - start < 10) {
                long total = 0;
                for (int i = start; i < end; i++) {
                    total += numbers[i];
                }
//                System.out.println("total:"+total);
                return total;
            }
            int middle = (end + start) / 2;
            SumTask subTask1 = new SumTask(start, middle);
            SumTask subTask2 = new SumTask(middle, end);
            subTask1.fork();
            subTask2.fork();
            return subTask1.join() + subTask2.join();
        }


    }


}
